<?php
// +----------------------------------------------------------------------
// | 后台用户管理
// +----------------------------------------------------------------------
namespace app\common\model;
use think\Model;
use think\Validate;

class GoodsSeckill extends Model
{
	use \base\model\ModelTrait;
	//goods模型关联，一对一关联
	public function goods(){
        return $this->hasOne('goods','id','goods_id');
    }
	//seckill模型关联，一对一关联
	public function activity(){
        return $this->hasOne('ActivitySeckill','id','activity_id');
    }
	/**
     * 错误信息
     */
	public $errorInfo;
	/**
     * 验证规则
     */
	protected $rule = [
		'activity_id|活动'=>'require|integer',
		'shop_id|店铺'=>'require|integer',
		'goods_id|商品'=>'require|integer',
    	'seckill_price|秒杀价格' => 'require|float|min:0',
    	'seckill_stock|秒杀库存' => 'require|float|min:1',
    	'seckill_num|秒杀数量' => 'require|float|min:1',
    	//'start_time' => 'require|date',
    	//'stop_time' => 'require|date|gt:start_time'
	];
	
	
	/**
    * 获取开始中的秒杀商品SQl语句
    * @return type
    */
	public function getGoodsSeckillSql($id=0)
    {
		$seckill = new self;
		$seckill = $seckill->alias('a');
		$seckill = $seckill->leftJoin('activity_seckill b','b.id=a.activity_id');
		$seckill = $seckill->where('a.is_del','0');
		$seckill = $seckill->where('a.status','1');
		if($id) $seckill = $seckill->where('a.id',$id);
		$seckill = $seckill->where('b.is_enable',1);
		$seckill = $seckill->where(function ($query) {
			$d =  date("Y-m-d"); $h =  date("H:i:s"); $dh =  date("Y-m-d H:i:s");
			$query->where(function ($query) use($d,$h,$dh) {
				$query->where('b.daily_num','=',0);
				$query->where('b.start_time','<=',$h);
				$query->where('b.stop_time','>=',$h);
			});
			$query->whereor(function ($query) use($d,$h,$dh) {
				$query = $query->where('b.daily_num','>',0);
				$query = $query->where([['','exp',\Db::raw("date_format(now(),'%Y-%m-%d') >= start_date")]]);
				$query = $query->where([['','exp',\Db::raw("date_format(now(),'%Y-%m-%d') <= date_add(b.start_date, interval daily_num-1 day)")]]);
				$query = $query->where('b.start_time','<=',$h);
				$query = $query->where('b.stop_time','>=',$h);
			});
		});
		$seckill = $seckill->field('a.id as seckill_id,a.seckill_price,a.seckill_stock,a.seckill_num');
		$seckill = $seckill->field('a.goods_id,a.activity_title');
		$seckill = $seckill->group('a.goods_id');
		if(!$id){
			return $seckill->buildSql();
		}else{
			return $seckill->find();
		}
    }
	
	
	/**
     * 获取秒杀商品
     * @param type $id
     * @return type
     */
	public function getSeckillList($where=[],$pageIndex=1,$pageSize=20)
    {
    	$where[] = ['is_del','=',0];
		$model = self::with([
			'goods'=>function($query) {
				$query->field('id,name,goods_no,img,banners,info,price');
				$query->field('sale_price,postage,unit,sales,ficti');
			},
			'activity'=>function($query) {
				$query->field('id,name,time_range,daily_num');
				$query->field('start_date,1 as start_date_range,1 as status');
			}
		]);
		$model = $model->where($where);
		$model = $model->order("sort_no");
		$model = $model->field("is_del,sort_no,is_postage",true);
		$model = $model->page($pageIndex,$pageSize);
		return $model->select();
    }
	
	/**
     * 获取结束时间大于当前的秒杀商品
     * @param $id
     * @param string $field
     * @return array|false|\PDOStatement|string|\think\Model
     */
    public static function getValidSeckill($id)
    {
    	return self::getGoodsSeckillSql($id);
    }
	
	
	/**
     * 获取库存
     * @param $id
     * @param string $field
     * @return array|false|\PDOStatement|string|\think\Model
     */
    public static function getStock($id)
    {
    	return self::where('id',$id)->value('seckill_stock');
    }

	/**
     * add秒杀商品
     * @param type $id
     * @return type
     */
	public function addSeckill($param)
    {
    	
    	$validate = new Validate;
		$validate->rule( $this->rule );
        if( !$validate->check($param) ) {
        	$this -> errorInfo = $validate->getError();
            return false;
        }
		
		$seckillStock = $param['seckill_stock'];
		
		//获取模型
		$db_goods =  model("Goods");
		//开启事务
		$db_goods->startTrans();
		
		try {
			
			//活动
			$activity = model('ActivitySeckill')->where('id',$param['activity_id'])->find();
			if(!$activity){
				$this->errorInfo = ' 未找到该该活动!';
				return false;
			}else{
				$param['activity_title'] = $activity["name"];
			}
			
			//秒杀商品
			$seckillGoods = new self;
			$seckillGoods = $seckillGoods->alias('a');
			$seckillGoods = $seckillGoods->leftJoin('activity_seckill b','b.id=a.activity_id');
			$seckillGoods = $seckillGoods->where('a.is_del','0');
			$seckillGoods = $seckillGoods->where('a.status','1');
			$seckillGoods = $seckillGoods->where('a.seckill_stock','>','0');
			$seckillGoods = $seckillGoods->where('a.goods_id',$param['goods_id']);
			$seckillGoods = $seckillGoods->where('b.is_enable',1);
			$seckillGoods = $seckillGoods->group('a.goods_id');
			$seckillGoods = $seckillGoods->find();
			if($seckillGoods){
				$this->errorInfo = '该商品已参加过活动，不能重复申请!';
				return false;
			}
			
			//商品
			$goods = $db_goods->where('id',$param['goods_id']);
			$goods =	 $goods->lock(true);
			$goods = $goods->field('( stock - frozen_stock ) as surplus_stock');
			$goods = $goods->find();
			if( !$goods ){
				$this->errorInfo = '未找到该商品!';
				return false;
			}
			
			if( $seckillStock > $goods['surplus_stock'] ){
				$this->errorInfo = '不能大于商品可用库存'.$goods['surplus_stock'].'!';
				return false;
			}
			
			$result = $db_goods->where('id',$param['goods_id'])->setInc("frozen_stock",$seckillStock);
			$result = self::allowField(true) -> save($param);
			
			if(!$result){
				$db_goods->rollback();
				$this->errorInfo = '异常错误!';
				return false;
			}else{
				$db_goods->commit();
				return $this;	
			}
			
		} catch (\Exception $e) {
			$db_goods->rollback();
			throw new \think\Exception( $e );
		}
    }
	
	
	/**
     * edit秒杀商品
     * @param type $id
     * @return type
     */
	public function editSeckill($param)
    {
    	$validate = new Validate;
		$validate->rule( [
			'id|秒杀id'=>'require|integer',
	    	'seckill_price|秒杀价格' => 'require|float|min:0',
	    	'seckill_stock|秒杀库存' => 'require|float|min:1',
	    	'seckill_num|秒杀数量' => 'require|float|min:1',
		]);
        if( !$validate->check($param) ) {
        	$this -> errorInfo = $validate->getError();
            return false;
        }
		
		if($param['goods_id']) unset($param['goods_id']);
		if($param['activity_id']) unset($param['activity_id']);
		$seckillStock = $param['seckill_stock'];
		
		//获取模型
		$db_goods =  model("Goods");
		//开启事务
		$db_goods->startTrans();
		
		try {
			
			//秒杀商品
			$seckill = self::get($param['id']);
			if(!$seckill){
				$this->errorInfo = '找不到该商品！';
				return false;
			}
			if($seckill['status'] == 1 ){
				$this->errorInfo = '该商品已通过审核，不能重复申请！';
				return false;
			}
			
			//商品
			$goods = $db_goods->where('id',$seckill['goods_id'])
				->lock(true)
				->field('( stock - frozen_stock ) as surplus_stock')
				->find();
			
			//商品库存
			$goodsStock = $goods['surplus_stock'] + $seckill['seckill_stock'];
			
			//判断库存
			if( $seckillStock > $goodsStock ){
				$db_goods->rollback();
				$this->errorInfo = '不能大于商品可用库存'.$goodsStock.'!';
				return false;
			}
			
			//是减还是加
			if( $seckillStock >= $seckill['seckill_stock'] ){
				$db_goods->where('id',$seckill['goods_id'])
					->setInc("frozen_stock",$seckillStock - $seckill['seckill_stock']);
			}else{
				$db_goods->where('id',$seckill['goods_id'])
					->setDec("frozen_stock",$seckill['seckill_stock'] - $seckillStock);
			}
			
			//更新
			$param['status'] = 0;
			$result = self::allowField(true)->isUpdate(true) -> save($param);
			
			if(!$result){
				$db_goods->rollback();
				$this->errorInfo = '异常错误!';
				return false;
			}else{
				$db_goods->commit();
				return $this;	
			}
			
		} catch (\Exception $e) {
			$db_goods->rollback();
			throw new \think\Exception( $e );
		}
    }

	
	/**
     * 删除秒杀商品
     * @param type $id
     * @return type
     */
	public function remove($id)
    {
    	//获取模型
		$db_goods = model("Goods");
		//开启事务
		$db_goods->startTrans();
		try {
			//秒杀商品
			$seckill = self::where('is_del',0)->get($id);
			if(!$seckill){
				$this->errorInfo = '找不到该商品！';
				return false;
			}
			//减库存
			$db_goods->where('id',$seckill['goods_id'])->setDec("frozen_stock",$seckill['seckill_stock']);
			//删除数据
			$result = self::where('id',$id)->update(['is_del'=>1]);
			if(!$result){
				$db_goods->rollback();
				return true;
			}
			//提交
			$db_goods->commit();
			return true;	
		} catch (\Exception $e) {
			$db_goods->rollback();
			throw new \think\Exception( $e );
		}
    }
	
	
	/**
     * 减库存
     * @param int $num
     * @param int $seckillId
     * @return bool
     */
    public  function decStock($seckillId = 0,$num = 0)
    {
		$goodsId = self::where('id', $seckillId)->value('goods_id');
        $res = $goodsId && self::where('id', $seckillId)
        	->dec('seckill_stock', $num)
        	->inc('seckill_sales', $num)
        	->update();
        $res = $res && model('goods')->where('id', $goodsId)
        	->dec('frozen_stock', $num)
        	->inc('sales', $num)
        	->update();
        return $res;
    }

    /**
     * 增加库存较少销量
     * @param int $num
     * @param int $seckillId
     * @return bool
     */
    public  function incStock($seckillId = 0,$num = 0)
    {
    	$goodsId = self::where('id', $seckillId)->value('goods_id');
        $res = $goodsId && self::where('id', $seckillId)
        	->inc('seckill_stock', $num)
        	->dec('seckill_sales', $num)
        	->update();
        $res = $res && model('goods')->where('id', $goodsId)
        	->inc('frozen_stock', $num)
        	->dec('sales', $num)
        	->update();
        return $res;
    }
	
}
